package monsmon.util;

import java.io.*;
import java.util.regex.*;
import java.awt.Color;
import java.lang.reflect.*;
import java.util.*;

/*
 * The class for misc methods that don't fit anywhere else
 */
public class Util{
	
	//Pattern used by str_to_col
	public static final Pattern colp = Pattern
			.compile("^#(\\d+):(\\d+):(\\d+)#$");

	public static final Pattern hcolp = Pattern
			.compile("^#([0-9A-F]{2}):([0-9A-F]{2}):([0-9A-F]{2})#$");



	//Strings for regex stuff
	private static String str = "\"(:?\\\\\"|[^\"])*\"";
	private static String inr = "(:?-|)\\d+";
	private static String flt = inr + "\\.\\d+";
	private static String tkn = "\\S+";
	//Maches an general token, for a function  call ex
	public static String argument = "(:?" + str + "|" + inr + "|" + flt 
		+ "|" + tkn + "|" + colp + "|" + hcolp + ")";

	private static int __ip(String s){
		return Integer.parseInt(s);
	}

	/*
	 * 	Returns color represented by s
	 * 	Avalible formats:
	 * 		#(red):(green):(blue)#	-- define your own color
	 * 		<name>	-- any color name already
	 * 				defined in java.awt.Color
	 *
	 */
	public static Color str_to_col(String s){
		if(s.charAt(0) == '#'){
			Matcher m = colp.matcher(s);
			if(m.matches()){
				return new Color(__ip(m.group(1)),
						__ip(m.group(2)),
						__ip(m.group(3)));
			}
			m = hcolp.matcher(s);
			if(m.matches()){
				return new Color(
						Integer.parseInt(m.group(1), 16),
						Integer.parseInt(m.group(2), 16),
						Integer.parseInt(m.group(3), 16));
			}
		}else{
			try{
				Class<Color> clz = Color.class;
				Field col = clz.getField(s);
				return (Color) col.get(null);
			}catch(Exception ex){
				System.out.println("No color called " + s);
				return null;
			}
		}
		return null;
	}

	/*
	 * Convinence method for turining a Stream into a buffered reader
	 */
	public static BufferedReader instream_to_bufdrdr(
			InputStream in) throws IOException{
		return new BufferedReader(new InputStreamReader(in));
	}

	/*
	 * Finds the longest string in the array
	 * 	returns the index of it
	 * 	if there are 2 strings of eq len, first is returned
	 * runs in O(n) time
	 */
	public static int lng_str(String s[]){
		int idx = 0;
		for(int i = 1; i < s.length; i++){
			if(s[i].length() > s[idx].length())
				idx = i;
		}
		return idx;
	}

	/*
	 * Reads a file entirely and returns it as a string
	 *
	 */
	public static String file_to_s(String fname){
		String s = null;
		FileInputStream f = null;
		try{
			File fi = new File(fname);
			f = new FileInputStream(fi);
			byte b[] = new byte[(int) fi.length()];
			f.read(b);
			s = new String(b);
		}catch(Exception e){
			e.printStackTrace();
			System.exit(1);
		}finally{
			if(f != null){
				try{
					f.close();
				}catch(IOException e){
					//No big deal if this happens, and
					//shouldn't
				}
			}
		}

		return s;
	}
	
	public static<K, V> V mgetd(Map<K, V> map, K get, V def){
		V g = map.get(get);
		if(g == null){
			return def;
		}
		return g;
	}

	private static int __find_col_len(String s, int sptr){
		char c = s.charAt(sptr);
		if(c == '#'){
			int lhs = s.indexOf('#', sptr + 1);
			return lhs + 1;
		}
		sptr++; 
		return sptr;
	}

	/*
	 * Removes opening and trailing quotes from a string
	 * 	Ex	"foo" 		-> foo
	 * 		"foo\"bar"	-> foo"bar
	 */
	public static String strip_quotes(String s){
		return s.substring(1, s.length() - 1).replace("\\\"", "\"");
	}
	
	/*
	 * Returns the real index of a fancy markup string from a 
	 * 	nominal index
	 * A nominal index is and index with the markup stripped from 
	 * 	the string
	 * A real index is the index needed for working with string
	 * 	methods (substring, charAt, indexOf)
	 * For example the string "a `Bfancy`b string"
	 *  the 'f' in fancy would have a real index of 4 but a 
	 *  nominal index of 2
	 */
	public static int sf_map_idx(String s, int idx){
		int sptr = 0, len = 0;
		char c = ' ';
		while(sptr < s.length()){
			c = s.charAt(sptr);
			switch(c){
				case '\n':
					sptr++;
					break;
				case '`':
					sptr++;
					if(sptr >= s.length()){
						//ERROR, should not happen
						return -1;
					}
					c = s.charAt(sptr);
					switch(c){
						case 'f':	//FALLTHRU
						case 'b':
						case '`':
						case 'K':
						case 'k':
						case 'S':
						case 's':
						case 'a':
							sptr++;
							break;
						case 'A':	//FALLTHRU
						case 'F':
						case 'B':
							//do something
							sptr++;
							sptr = __find_col_len(
								s, sptr);
							break;
					}
				default:
					len++;
					if(len == idx){
					       break;
				      	}	       
			}
		}
		return sptr;
	}

	/*
	 * Returns the nominal length of a fancy string.
	 * The nominal length of a fancy string is the actual length
	 *  minus the formating markup, it is the length if the 
	 *  string was printed with TermUtil.swritef()
	 */
	public static int sf_len(String s){
		int sptr = 0, len = 0;
		char c = ' ';
		while(sptr < s.length()){
			c = s.charAt(sptr);
			switch(c){
				case '\n':
					sptr++;
					break;
				case '`':
					sptr++;
					if(sptr >= s.length()){
						//ERROR, should not happen
						return -1;
					}
					c = s.charAt(sptr);
					switch(c){
						case 'f':	//FALLTHRU
						case 'b':
						case '`':
						case 'K':
						case 'k':
						case 'S':
						case 's':
						case 'a':
							sptr++;
							break;
						case 'A':	//FALLTHRU
						case 'F':
						case 'B':
							//do something
							sptr++;
							sptr = __find_col_len(
								s, sptr);
							break;
					}
				default:
					len++;
					sptr++;
			}
		}
		return len;
	}
}
